// This source code demonstrates how to connect to Access 2007
// .accdb database from C++ using the DAO Data Access Technology.
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This sample code is provided to illustrate a concept and 
// should not be used in applications or Web sites, as it 
// may not illustrate the safest coding practices. Microsoft 
// assumes no liability for incidental or consequential damages 
// should the sample code be used for purposes 
// other than as intended.

#import <C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\ACEDAO.dll>  \
    rename( "EOF", "AdoNSEOF" )

#include <iostream>
#include <tchar.h>

using namespace std;

// Data Access Method used in this sample
const char* DAM = "Direct DAO";

// Connection string for Direct DAO 
_bstr_t bstrConnect = "C:\\Northwind 2007.accdb";

int _tmain(int argc, _TCHAR* argv[])
{
    // Initialize the Component Object Module Library (COM)
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        cout<<DAM<<": Failed to CoInitialize() COM."<<endl;
        return hr;
    }

    // Create an instance of the engine
    DAO::_DBEngine* pEngine = NULL;

    // The CoCreateInstance helper function provides a convenient shortcut by connecting 
    // to the class object associated with the specified CLSID, creating an 
    // uninitialized instance, and releasing the class object. 
    hr = CoCreateInstance(
        __uuidof(DAO::DBEngine),
        NULL,
        CLSCTX_ALL,
        IID_IDispatch,
        (LPVOID*)&pEngine);
    if (SUCCEEDED(hr) && pEngine)
    {
        // COM errors are handled by C++ try/catch block
        try
        {
            DAO::DatabasePtr pDbPtr = NULL;
            pDbPtr = pEngine->OpenDatabase(bstrConnect);
            if (pDbPtr)
            {
                cout<<DAM<<": Successfully connected to database. Data source name:\n  "
                    <<pDbPtr->GetName()<<endl;

                // Prepare SQL query.
                _bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM Customers;";
                cout<<DAM<<": SQL query:\n  "<<query<<endl;

                // Excecute the query and create a record set
                DAO::RecordsetPtr pRS = NULL;
                pRS = pDbPtr->OpenRecordset(query, _variant_t(DAO::dbOpenDynaset));
                if (pRS && 0 < pRS->RecordCount)
                {
                    cout<<DAM<<": Retrieve schema info for the given result set: "<<endl;
                    DAO::FieldsPtr pFields = NULL;
                    pFields = pRS->GetFields();
                    if (pFields && pFields->Count > 0)
                    {
                        for (short nIndex=0; nIndex < pFields->Count; nIndex++)
                        {
                            cout<<" | "<<pFields->GetItem(nIndex)->GetName();
                        }
                        cout<<endl;
                    }
                    else
                    {
                        cout<<DAM<<": Error: Number of fields in the result set is 0."<<endl;
                    }

                    cout<<DAM<<": Fetch the actual data: "<<endl;
                    // Loop through the rows in the result set
                    while (!pRS->AdoNSEOF)
                    {
                        for (short nIndex=0; nIndex < pFields->Count; nIndex++)
                        {
                            cout<<" | "<<_bstr_t(pFields->GetItem(nIndex)->GetValue());
                        }
                        cout<<endl;
                        pRS->MoveNext();
                    }
                    cout<<DAM<<": Total Row Count: "<<pRS->RecordCount<<endl;
                }

                // Close record set and database
                pRS->Close();
                pDbPtr->Close();
                pDbPtr = NULL;
            }
            else
            {
                cout<<DAM<<": Unable to connect to data source: "<<bstrConnect<<endl;
            }
        }
        catch(_com_error& e)
        {
            cout<<DAM<<": _com_error: "<<e.Description()<<endl;
        }
        
        pEngine->Release();
        pEngine = NULL;
        cout<<DAM<<": Cleanup. Done."<<endl;
    }
    else
    {
        cout<<DAM<<": Cannot instantiate DBEngine object."<<endl;
    }

    // Release the Component Object Module Library (COM)
    CoUninitialize();
    return hr;
}